#pragma once
#include "sock.hpp"
#include <unistd.h>
#include <poll.h>
#include <vector>


#define DEFAULTPORT 8080
#define ANYIP "0.0.0.0"
#define POLLSIZE 10000
#define defaults -1

typedef std::string(*fun_t)(std::string);

namespace ServerFile
{

    class Server
    {
        void HandlerAccept()
        {
            // 说明已经准备好，可以提取accept了
            std::string ClinetIP;
            uint16_t ClinetPort;
            int sock = Sock::Accpet(_listensock, ClinetIP, ClinetPort);

            if (sock < 0)
                return;

            if (sock > 0)
            {
                // 若sock > 0 那么后续sock要关注读写，所以我们把sock加入到 _fdnums中
                int i = 0;
                for (; i < POLLSIZE; i++)
                    if (_pollnums[i].fd == defaults)
                        break;

                if (i == POLLSIZE)
                    std::cout << "可监管的sock套接字已满，请稍等业务处理之后再来吧" << std::endl;
                else
                {
                    _pollnums[i].fd = sock;
                    _pollnums[i].events = POLLIN;
                    std::cout <<"socket = " << sock <<"已经被设置到select中" << std::endl;
                }
            }
        }

        void HandlerRead(int pos)
        {
             //我要申明一下这里不能确保读到一个报文，要确保读到一个报文那得 约定报头，while循环读取

             int exitsockfd = defaults;
             char buffer[1024];
             ssize_t s = read(_pollnums[pos].fd,buffer,sizeof buffer - 1);

             if(s > 0)
             {
                buffer[s-1] = 0;
             }
             else if(s == 0)
             {
                exitsockfd = _pollnums[pos].fd;
                close(_pollnums[pos].fd);
                initpollfd(pos);
             }
             else
             {
                logMessage(FATAL);
                exit(READ_ERRON);
             }

             //到这里我们得处理读取上来的数据了
             std::string response = _fun(buffer);

             int n = write(_pollnums[pos].fd,response.c_str(),response.size()); 
             if(n < 0)
             {
                logMessage(WARNING);
                std::cout << "检测到socket = " << exitsockfd << "退出" << std::endl;
             }

        }

        void HandlerTask()
        {
            //能走到这里代表有就绪的套接字
            for (int i = 0; i < POLLSIZE ; i++)
            {
                if(_pollnums[i].fd == defaults) continue;

                 //今天我们只关心可读状态
                if(_pollnums[i].events != POLLIN) continue;
     
      
                //不要低估计算机的速度
                //这边在等待accept
                if(_pollnums[i].fd == _listensock && _pollnums[i].revents == POLLIN)
                HandlerAccept();
                //这边在等待底层缓冲区有数据
                else if(_pollnums[i].fd != defaults && _pollnums[i].revents == POLLIN)
                HandlerRead(i);
            }
        }

    public:
        Server(fun_t fun_t,uint16_t port = DEFAULTPORT)
            : _port(port)
            , _fun(fun_t)
        {
            _pollnums = new struct pollfd[POLLSIZE];

            for(int i = 0 ; i < POLLSIZE ; i++) initpollfd(i);

        }

        void initpollfd(int pos)
        {
            _pollnums[pos].fd = defaults;
            _pollnums[pos].events = 0;
            _pollnums[pos].revents = 0;
        }

        // 创建监听套接字，bind链接，设置listen监听
        void init()
        {
            _listensock = Sock::SetSocket();
            Sock::Bind(_listensock, ANYIP, _port);
            Sock::Listen(_listensock);

         
            _pollnums[0].fd = _listensock;
            _pollnums[0].events = POLLIN;
        }



        void start()
        {
            int timeout = 2000;
            for (;;)
            {
             
                // struct timeval times = {5, 0}; // 第一个表示秒,第二个表示毫秒
                int n = poll( _pollnums, POLLSIZE, timeout);
                if (n > 0)
                {
                    HandlerTask();
                }
                else if (n == 0)
                {
                    continue;
                }
                else
                {
                    logMessage(FATAL);
                    exit(SELECT_ERRON);
                }
            }
        }

        ~Server()
        {
            if (_listensock > 0)
                close(_listensock);

            if(_pollnums) delete []_pollnums;
        }

    private:
        // 需要套接字和端口号
        int _listensock;
        uint16_t _port;
       // std::vector<struct pollfd> _pollNums;

       struct pollfd* _pollnums;
        fun_t _fun;
    };
}